//
//  WNLayout.swift
//  WalkNovel
//
//  Created by Kevin on 2023/7/4.
//

import UIKit

protocol WNLayoutDelegate {
    func width4ItemAtIndexPath(index: IndexPath) -> CGFloat
    func lineNumber(number: Int)
}

class WNLayout: UICollectionViewLayout {

    var lineNumber: Int = 1
    var columSpace: CGFloat = 12
    var rowSpace: CGFloat = 12
    var height: CGFloat = 30
    var delegate: WNLayoutDelegate?
    var attrArray = [UICollectionViewLayoutAttributes]()
    var inset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
    var tempX: CGFloat = 0
    var tempY: CGFloat = 0
    
    override func prepare() {
        super.prepare()
        tempX = inset.left
        tempY = inset.top
        lineNumber = 1
        let itemCount = collectionView?.numberOfItems(inSection: 0)
        for i in 0..<itemCount! {
            computeItemLayout(i)
        }
    }
    
    func computeItemLayout(_ index: Int) {
        let indexPath = IndexPath(item: index, section: 0)
        var x = tempX
        var y = tempY
        let w = delegate?.width4ItemAtIndexPath(index: indexPath)
        let h = height
        // 更新y/w
        tempX += (w! + columSpace)
        // 换行判断
        if tempX > (collectionView?.bounds.size.width)! - inset.right {
            x = inset.left
            tempX = w! + columSpace + inset.left
            tempY += (height + rowSpace)
            y = tempY
            lineNumber += 1
            delegate?.lineNumber(number: lineNumber)
        }
        let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
        attr.frame = CGRect(x: x, y: y, width: w!, height: h)
        attrArray.append(attr)
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attrArray
    }
    
    override var collectionViewContentSize: CGSize {
        return CGSize(width: (collectionView?.bounds.size.width)!, height: tempY + height)
    }
}

protocol WaterfallLayoutDelegate: NSObjectProtocol {

    func waterFlowLayout(_ layout: WaterFallLayout, _ indexPath: IndexPath, _ width: CGFloat) -> CGFloat
}

class WaterFallLayout: UICollectionViewFlowLayout {

    var delegate: WaterfallLayoutDelegate?
    // 瀑布流的列数
    var watefallColumns = 2
    // 列间距
    var columnsSpacing: CGFloat = 20
    // 行间距
    var lineSpacing: CGFloat = 20
    // 创建存放当前加载的Cell 的布局属性
    var cellLayoutAttributes: NSMutableArray?
    // 创建存放Cell 所在列的高度
    var cellColumnsHeights: NSMutableArray?
    // cell 内容的高度
    var contentHeight:CGFloat?
    
    override func prepare() {
        super.prepare()
        contentHeight = 0.0
        cellColumnsHeights = NSMutableArray.init(capacity: 0)
        cellLayoutAttributes = NSMutableArray.init(capacity: 0)
        for _ in 0 ..< watefallColumns {
            cellColumnsHeights?.add(self.sectionInset.top)
        }
        let loadCellCount = self.collectionView?.numberOfItems(inSection: 0)
        for i in 0 ..< loadCellCount! {
            let indexPath = IndexPath.init(row: i, section: 0)
            let cellAttribute = self.layoutAttributesForItem(at: indexPath)
            cellLayoutAttributes?.add(cellAttribute!)
        }
    }
    
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let cellWidth = ((self.collectionView?.bounds.width)! - lineSpacing * CGFloat(watefallColumns - 1)-self.sectionInset.left - self.sectionInset.right) / CGFloat(watefallColumns)
        let cellHight = delegate?.waterFlowLayout(self, indexPath ,cellWidth)
        var minColumnsCellHeight = cellColumnsHeights?.firstObject as! CGFloat
        var minColumnCellMark = 0
        for i in 0 ..< watefallColumns {
            let tempCellHeight = cellColumnsHeights?[i] as! CGFloat
            if minColumnsCellHeight > tempCellHeight {
                minColumnsCellHeight = tempCellHeight
                minColumnCellMark = i
            }
        }
        let minCellHeightX =  CGFloat(minColumnCellMark) * (cellWidth + columnsSpacing) + self.sectionInset.left
        var cellHeightY = minColumnsCellHeight
        if cellHeightY != self.sectionInset.top {
             cellHeightY += lineSpacing
        }
        let LayoutAttribute = UICollectionViewLayoutAttributes.init(forCellWith: indexPath)
        LayoutAttribute.frame = CGRect.init(x: minCellHeightX, y: cellHeightY, width: cellWidth, height: cellHight!)
        cellColumnsHeights?[minColumnCellMark] = LayoutAttribute.frame.maxY
        let minCellHeightY = cellColumnsHeights?[minColumnCellMark] as! CGFloat
        if contentHeight! < minCellHeightY {
            contentHeight = minCellHeightY
        }
        return LayoutAttribute
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return (cellLayoutAttributes as! [UICollectionViewLayoutAttributes])
    }
    
    override var collectionViewContentSize: CGSize {
        get {
            return CGSize.init(width: (self.collectionView?.frame.width)!, height: maxH(cellColumnsHeights!))
        }
        set {
            self.collectionViewContentSize = newValue
        }
    }
    
    func maxH(_ cellHeight: NSMutableArray) -> CGFloat {
        var max = cellHeight.firstObject as! CGFloat
        for i in 0 ..< cellHeight.count {
            if max < (cellHeight[i] as! CGFloat) {
                max = cellHeight[i] as! CGFloat
            }
        }
        return max + self.sectionInset.bottom
    }
}
